﻿//AcademicPlanner - course registration planning web app.
//Copyright (C) 2009  Boubacar Diallo

//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


using System;
using System.Collections;
using AcademicPlanner.Data.Entities;
using NHibernate.Tool.hbm2ddl;
using NHibernate;

namespace AcademicPlanner.Data.Repositories
{
	/// <summary>
	/// PersonEntityRepository serves as the repository for <c>PersonEntity</c>s.
	/// </summary>
	/// <version>1.0</version>
	/// <since>1.0</since>
	public class PersonEntityRepository : EntityRepository<PersonEntity>
	{
		internal override string DBTableName { get { return "people"; } }


		private PersonEntityRepository()
		{
			namedQueriesPrefix = "PersonEntity";
		}

		private class InstanceHolder
		{
			internal static PersonEntityRepository INSTANCE = new PersonEntityRepository();
		}


		/// <summary>
		/// The the single instance of PersonEntityRepository.
		/// </summary>
		/// <returns>The single instance of PersonEntityRepository.</returns>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public static PersonEntityRepository GetInstance()
		{
			return InstanceHolder.INSTANCE;
		}

		/// <summary>
		/// Finds the <c>PersonEntity</c> that has the given email address from
		/// the persistence layer.
		/// </summary>
		/// <param name="pEmail">The email address to find a macthing <c>PersonEntity</c> for.</param>
		/// <returns>The <c>PersonEntity</c> or <c>null</c>.</returns>
		/// <exception cref="T:AcademicPlanner.Data.DataException">
		/// Thrown with an error code of <c>DataErrorCode.QUERY_PERSON_ENTITY_BY_EMAIL_FAILED</c>
		/// when an error is reported by NHibernate. The <c>HibernateException</c> is
		/// accessible via the <c>InnerException</c> property.
		/// </exception>
		/// <seealso cref="M:GetNamedQuery"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public PersonEntity FindByEmail(string pEmail)
		{
			PersonEntity rEnt = null;

			try
			{
				var vQuery = GetNamedQuery("by.email");
				vQuery.SetString("email", pEmail);
				rEnt = (PersonEntity)vQuery.UniqueResult();
			}
			catch (HibernateException vHx)
			{
				var vDx = new DataException(DataErrorCode.QUERY_PERSON_ENTITY_BY_EMAIL_FAILED, vHx);
				throw vDx;
			}

			return rEnt;
		}

		/// <summary>
		/// Finds the <c>PersonEntity</c> that has an <c>AccountEntity</c> with a
		/// <c>UserEntity</c> with the given username from the persistence layer.
		/// </summary>
		/// <param name="pAccountEntityUserEntityName">The username.</param>
		/// <returns>The <c>PersonEntity</c> or <c>null</c>.</returns>
		/// <exception cref="T:AcademicPlanner.Data.DataException">
		/// Thrown with an error code of <c>DataErrorCode.QUERY_PERSON_ENTITY_BY_ACCOUNT_ENTITIES_USER_ENTITY_NAME_FAILED</c>
		/// when an error is reported by NHibernate. The <c>HibernateException</c> is
		/// accessible via the <c>InnerException</c> property.
		/// </exception>
		/// <seealso cref="M:GetSqlQuery"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public PersonEntity FindByAccountEntityUserEntityName(string pAccountEntityUserEntityName)
		{
			PersonEntity rEnt = null;
			var vSql = string.Format(
				"SELECT p.* " +
				"FROM {0} p " +
				"	JOIN {1} a ON a.person_id = p.id " +
				"	JOIN {2} u ON u.id = a.user_id " +
				"WHERE u.name = :accountEntityUserEntityName " +
				"	AND p.trashed = 0",
				DBTableName, DSAS.AccountEntityRepo.DBTableName, DSAS.UserEntityRepo.DBTableName);

			try
			{
				var vQuery = GetSqlQuery(vSql);
				vQuery.AddEntity(typeof(PersonEntity));
				vQuery.SetString("accountEntityUserEntityName", pAccountEntityUserEntityName);
				rEnt = vQuery.UniqueResult<PersonEntity>();
			}
			catch (HibernateException vHx)
			{
				var vDx = new DataException(DataErrorCode.QUERY_PERSON_ENTITY_BY_ACCOUNT_ENTITIES_USER_ENTITY_NAME_FAILED, vHx);
				throw vDx;
			}

			return rEnt;
		}


	}
}
